import type { ComponentType, FormSchema } from "@/typings/dynamic-search";
import {
  PageRequest,
  FilterGroup,
  PageCondition,
  SortCondition,
  SortConditionEnum,
  FilterRule,
  FilterOperateEnum,
  Filter,
} from "@/util/page-request";
import { notEmpty } from "@/util";

type comEventType = (schema: FormSchema) => void;

export const usePageRequest = (formSchema: FormSchema[]) => {
  const commonEvent = (schema: FormSchema) => {
    if (!notEmpty(schema.value)) return;
    const { code, value, operate, extraCode, extraOp } = schema;
    if (schema.isGroup) {
      const rules: FilterRule[] = [new FilterRule(code, value, operate), new FilterRule(extraCode!, value, operate)];
      filterGroup.push(new FilterGroup(rules, extraOp!));
    } else {
      filterRules.push(new FilterRule(code, value, operate));
    }
  };

  const inputEvent = (schema: FormSchema) => {
    commonEvent(schema);
  };
  const selectEvent = (schema: FormSchema) => {
    commonEvent(schema);
  };
  const datePickerEvent = (schema: FormSchema) => {
    if (!notEmpty(schema.value)) return;
    const { code, value, operate, extraOp, datePickerType } = schema;
    if (["date", "datetime"].includes(datePickerType!)) {
      commonEvent(schema);
    } else if (datePickerType === "daterange") {
      const rules: FilterRule[] = [
        new FilterRule(code, value[0], operate || FilterOperateEnum.GREATER_THAN_EQUAL_TO),
        new FilterRule(code, value[1], extraOp || FilterOperateEnum.LESS_THAN),
      ];
      filterRules.push(...rules);
    }
  };

  const eventMap: Record<ComponentType, comEventType> = {
    Input: inputEvent,
    Select: selectEvent,
    DatePicker: datePickerEvent,
  };

  const sortConditions: SortCondition[] = [];
  const genSortCondition = (field: string, sort: SortConditionEnum) => {
    const hasOrder = sortConditions.some((item) => field === item.field);
    if (hasOrder) return;
    sortConditions.push(new SortCondition(field, sort));
  };
  const resetSortConditions = () => {
    sortConditions.length = 0;
  };

  let pageCondition: PageCondition = new PageCondition(1, 10, sortConditions);
  const genPageCondition = (
    pageIndex: number = pageCondition.pageIndex,
    pageSize: number = pageCondition.pageSize,
    sorts: SortCondition[] = sortConditions
  ) => {
    pageCondition = new PageCondition(pageIndex, pageSize, sorts);
  };
  const resetPageCondition = () => {
    pageCondition = new PageCondition(1, 10, []);
  };

  const filterRules: FilterRule[] = [];
  const resetFileRules = () => {
    filterRules.length = 0;
  };

  const filterGroup: FilterGroup[] = [];
  const resetFilterGroup = () => {
    filterGroup.length = 0;
  };

  let filter: Filter = new Filter(filterGroup, filterRules);
  const resetFilter = () => {
    filter = new Filter([], []);
  };

  let pageRequest: PageRequest = new PageRequest(pageCondition, filter);
  const genPageRequest = () => {
    resetPageRequest();
    for (const schema of formSchema) {
      const event = eventMap[schema.type];
      event(schema);
    }
    filter = new Filter(filterGroup, filterRules);
    pageRequest = new PageRequest(pageCondition, filter);
  };

  const resetFormSchema = () => {
    for (const schema of formSchema) {
      schema.value = null;
    }
  };

  const resetPageRequest = () => {
    resetFileRules();
    resetFilterGroup();
    resetFilter();
  };

  const reset = () => {
    resetPageRequest();
    resetFormSchema();
  };

  return {
    sortConditions,
    genSortCondition,
    resetSortConditions,

    pageCondition,
    genPageCondition,
    resetPageCondition,

    filterRules,
    resetFileRules,

    filterGroup,
    resetFilterGroup,

    filter,
    resetFilter,

    pageRequest,
    genPageRequest,
    resetPageRequest,
    reset,
  };
};
